;+
;PURPOSE
;	to make a plot with histograms of the x and y distributions
;	along those axes
;SYNTAX
; plot_w_histo, x, y [, _extra=_extra,extra_xhist=extra_xhist,
;                extra_yhist=extra_yhist, nybin=nybin, nxbin=nxbin, /xhist,
;                /yhist, x_min_border=x_min_border, x_max_border=x_max_border,
;                y_min_border=y_min_border, y_max_border=y_max_border,
;                 widthxhist=widthxhist, widthyhist=widthyhist, /normyhist,
;                /normxhist, rangeyhist=rangeyhist, rangexhist=rangexhist,
;		/matchticklength, /xminor, /yminor]
;
;INPUTS
;keyword inheritance:_________________________________________________________
;	_extra: extra keywords to pass to main plot
;	extra_yhist: extra keywords to pass to the yhistogram
;	NOTE!	(e.g. if you want the yhistogram to have linestyle=1 you would 
;		call the program as follows:
;		plot_w_histo, x, y, /yhist, extra_yhist={linestyle:1}	
;	extra_xhist: extra keywrods to pass to the xhistogram (see note above)
;Other:_______________________________________________________________________
;	nxbin: number of bins in x axis histogram
;	nybin: number of bins in y axis histogram
;	/xhist: make the x-histogram
;	/yhist: make the y-histogram
;	x_min_border: in normalized units how much or a border do you want
;			[default 0.15]
;       x_max_border: in normalized units how much or a border do you want
;                       [default 0.95]
;       y_min_border: in normalized units how much or a border do you want
;                       [default 0.15]
;       y_max_border: in normalized units how much or a border do you want
;                       [default 0.95]
;	widthxhist: in normalized units how big do you want the x histogram
;			[default 0.2]
;	widthyhist: in normalized units how big do you wnat the y histogram
;			[default 0.2]
;	/normyhist: set to normalize the yhistogram
;	/normxhist: set to normalize the xhistogram
;	rangeyhist: range for the number axis of the y histogram
;	rangexhist: range for the number axis of the x histogram
;	/nomatchticklength: set to NOT match the ticklengths of main and 
;			histogram plots
;	/xminor: enable minor tick marks on x histogram
;	/yminor: enable minor tick marks on y histogram
;NOTES
; +Make use of the extra_yhist and extra_xhist keywords. They are powerful!
; +Only support p.multi with !p.multi[4]=0... if you don't know what this
; 	means then don't worry about it
; +I strongly suggest use of the !p system variable rather than passing plot, 
; 	keywords especially if you aren't getting the results you want. This
;	eliminates the need of duplicate keyword calls and makes things
;	much easier to change
; +If you are having problems with the xhistogram yaxis hitting the figures
;	then use rangexhist
;
;TO BE ADDED IN NEXT VERSION
;	+allow oplots of gaussian fits etc...
;	+get xhist yaxis to always look good (not have to tweak it sometimes)
;
;Written by R. da Silva, UCSC, 3-12-10
;-
pro plot_w_histo, x, y, _extra=_extra, nybin=nybin, nxbin=nxbin, xhist=xhist,$
		yhist=yhist, x_min_border=x_min_border, $
		x_max_border=x_max_border,$
		y_min_border=y_min_border, y_max_border=y_max_border,$
		 widthxhist=widthxhist, widthyhist=widthyhist, $
		normyhist=normyhist,$
		normxhist=normxhist, rangeyhist=rangeyhist, $
		rangexhist=rangexhist, $
		nomatchticklength=nomatchticklength, xminor=xminor, $
		yminor=yminor, xtitle=xtitle, extra_xhist=extra_xhist,$
		extra_yhist=extra_yhist
;set some defaults
if not keyword_set(x_min_border) then x_min_border=.15;0.08
if not keyword_set(x_max_border) then x_max_border=0.95
if not keyword_set(y_min_border) then y_min_border=0.15;0.08
if not keyword_set(y_max_border) then y_max_border=0.95
if not keyword_set(widthxhist) then widthxhist=keyword_set(xhist)*.2
if not keyword_set(widthyhist) then widthyhist=keyword_set(yhist)*.2
;figure out where I am in p.multi
spaces=replicate(' ', 10)
xm0=!x.margin
ym0=!y.margin
ncols=!p.multi[1] > 1
nrows=!p.multi[2] > 1
elem1=!p.multi[0]
if elem1 NE 0 then elem=ncols*nrows-elem1 else elem=elem1
if total(!p.multi) NE 0 then begin
col=elem mod ncols
row=floor(elem/ncols)
xoffset=float(col)/ncols
yoffset=float(nrows-row-1)/nrows
endif else begin
xoffset=0
yoffset=0
pmultieq0=1
endelse

;draw region for main plot
x0=x_min_border
y0=y_min_border+widthxhist
x1=x_max_border-widthyhist
y1=y_max_border
!p.region=[x0/ncols + xoffset,y0/nrows + yoffset, x1/ncols +xoffset , $
	y1/nrows + yoffset]
if keyword_set(xhist) then spaces1=spaces
!x.margin=[0, 0]
!y.margin=[0,0]


;----------plot the data----------------------------

if NOT keyword_set(xhist) then xtitle1=xtitle
plot, x, y,xtickname=spaces1, _extra=_extra, xtitle=xtitle1
xrr=!x.crange
yrr=!y.crange
resx=histogram(x, min=xrr[0], max=xrr[1], nbins=nxbin, loc=xloc)
if keyword_set(normxhist) then resx=float(resx)/n_elements(x)
resy=histogram(y, min=yrr[0], max=yrr[1], nbins=nybin, loc=yloc)
if keyword_set(normyhist) then resy=float(resy)/n_elements(y)
;---------figure out region and plot the x histogram--------------------
if keyword_set(xhist) then begin
x0=x_min_border
y0=y_min_border
x1=x_max_border-widthyhist
y1=widthxhist+y_min_border
!x.margin=[0, 0]
!y.margin=[0,0]
!p.region=[x0/ncols + xoffset,y0/nrows + yoffset, x1/ncols +xoffset , $
        y1/nrows + yoffset]
if NOT keyword_set(nomatchticklength) then $
     xticklen1=!p.ticklen*(y_max_border-(y_min_border+widthxhist))/float(y1-y0)

;deal with connecting last point to zero robustly
binss=xloc[1]-xloc[0]

;the +binss/2 is because histogram locations aren't the centers of the bins
;---plot with no data to get data ranges
plot,xloc+binss/2, resx, ps=10, /noerase, xr=xrr, yr=rangexhist, $
        xticklen=xticklen1, ytickname=spaces, yminor=~ keyword_set(xminor),$
        xtitle=xtitle, /nodata, ticklen=0
;make x number not hit top of plot
if not keyword_set(rangexhist) then begin
rangexhist=!y.crange
rangexhist[1]+=.5*(!y.crange[1]-!y.crange[0])/6.
endif

plot,xloc+binss/2, resx, ps=10, /noerase, xr=xrr, yr=rangexhist, $
	xticklen=xticklen1, ytickname=spaces, yminor=~ keyword_set(xminor),$
	xtitle=xtitle, _extra=extra_xhist, ystyle=1
;plot lines in between bins
for ifill=0, n_elements(xloc)-1 do begin
    oplot, [xloc[ifill],xloc[ifill]], [0, resx[ifill]], _extra=extra_xhist
    oplot, [xloc[ifill],xloc[ifill]]+binss, [0, resx[ifill]], _extra=extra_xhist
endfor
oplot, [min(xloc), min(xloc), min(xloc)+binss/2], [0, resx[0], resx[0]]$
	, _extra=extra_xhist
oplot, [max(xloc), max(xloc)]+binss/2, [0, resx[n_elements(resx)-1]]$
	, _extra=extra_xhist

axis, yaxis=1, yminor=~ keyword_set(xminor), ystyle=keyword_set(rangexhist),$
	charsize=1,_extra=extra_xhist
endif

;--------------figure out region and plot the y histogram----------------
if keyword_set(yhist) then begin
x0=x_max_border-widthyhist
y0=y_min_border+widthxhist
x1=x_max_border
y1=y_max_border
!p.region=[x0/ncols + xoffset,y0/nrows + yoffset, x1/ncols +xoffset , $
        y1/nrows + yoffset]
;I have to deal with the fact that ps=10 won't work for the sideways plot
binsizes=abs(yloc[1]-yloc[0])
yyy=[resy, resy, resy]
eps=binsizes/10;have to subtract eps to make the sort robust
yxx=[yloc, yloc-binsizes/2., yloc+binsizes/2.-eps]+binsizes/2.
isort=sort(yxx)
yxx=yxx[isort]
yyy=yyy[isort]
yxx[lindgen(n_elements(yloc))*3+2]+=eps
;deal with connecting last point to zero robustly
yxx=[min(yxx), yxx, max(yxx)]
yyy=[0, yyy, 0]
if NOT keyword_set(nomatchticklength) then $
        yticklen1=!p.ticklen*(x_max_border-widthyhist-x_min_border)/float(x1-x0)
plot, yyy,yxx, ytickname=spaces, /noerase, yr=yrr, xr=rangeyhist, $
	xtickname=spaces, yticklen=yticklen1, xminor=~ keyword_set(yminor),$
	_extra=extra_yhist
axis, xaxis=1,xminor=~ keyword_set(yminor), charsize=1, _extra=extra_yhist
	;redraw x-axis on top or runs into x-axis of other plots
endif
for icount=0, n_elements(yloc)-1 do begin
	oplot, [0, resy[icount]],[yloc[icount], yloc[icount]],_extra=extra_yhist
endfor


;reset plot parameters since I touched a bunch of them
if elem1 NE 0 then !p.multi[0]=(elem1-1) else !p.multi[0]=nrows*ncols-1
!p.region=0
!x.margin=xm0
!y.margin=ym0
!x.crange=xrr
!y.crange=yrr
if keyword_set(pmultieq0) then !p.multi=0
end
